SuperStrict
NoDebug
  
Rem  
bbdoc: MaxMod.Ogg
End Rem
Module MaxMod.OGG
ModuleInfo "MaxMod: OGG - v1.25"
ModuleInfo "Author: REDi - Cliff Harman"
ModuleInfo "License: MIT"

Import BRL.StandardIO
Import MaxMod.Music
Import BRL.FileSystem
'Import BRL.Retro
Import PUB.OggVorbis
	
MaxModLoader.Create(MaxMod_Loader_Ogg,"Ogg Vorbis ~q.ogg~q","ogg")

Function MaxMod_Loader_Ogg:TMusic(File:Object)
	Local Ogg:TMusic = TOGGStream.Load(File)
	Return Ogg
EndFunction



' "borrowed" from brl.oggloader :)
Private

Function readfunc:Int( buf@Ptr,size:Int,nmemb:Int,src:Object )
	Local bytes:Int=TStream(src).Read(buf,size*nmemb)
	Return bytes/size
End Function

Function seekfunc:Int( src_obj:Object,off0:Int,off1:Int,whence:Int )
	Local off:Int
	Local src:TStream=TStream(src_obj)
?X86
	off=off0
?PPC
	off=off1
?
	Local res:Int=-1
	Select whence
		Case 0
			res=src.Seek(off)			'SEEK_SET
		Case 1
			res=src.Seek(src.Pos()+off)	'SEEK_CUR
		Case 2
			res=src.Seek(src.Size()+off)'SEEK_END
	End Select
	If res>=0 Return 0
	Return -1
End Function

Function closefunc( src:Object )
End Function

Function tellfunc:Int( src:Object )
	Return TStream(src).Pos()
End Function

Public

Rem
bbdoc: Provides OGG format streaming. 
End Rem
Type TOGGStream Extends TMusic

	Field stream:TStream
	Field ogg:Byte Ptr
	Field samples:Int			' number of sample in ogg
	Field size:Int				' in bytes
	
'	Field Socket:TSocket
	
	Function Load:TOGGStream(File:Object)
	
		Local samples:Int,channels:Int,freq:Int

		Local Stream:TStream = OpenFile(File,True,False)
		If Not Stream Return Null
		Local ogg:Byte Ptr 	 = Decode_Ogg(Stream,readfunc,seekfunc,closefunc,tellfunc,samples,channels,freq)
		If Not ogg Return Null

		Local This:TOGGStream
		This 				= New TOGGStream
		This.Stream 		= Stream
'		This.samples 		= Samples
		This.ogg 			= Ogg
		This.Sample_Rate 	= Freq
		This.Stream_Size	= samples
'		If channels=1 This.STREAM_FORMAT=AL_FORMAT_MONO16 Else This.STREAM_FORMAT=AL_FORMAT_STEREO16

		Return This
		
	EndFunction


'	Function OpenIceStream:MaxMod_OggStream(Host$, File$,remotePort:Int)
'
'		Local samples:Int,freq:Int,channels:Int=2,SampleRate:Int 
'	
'		Local socket:TSocket = CreateTCPSocket()
'		If Not ConnectSocket(socket, HostIp(Host), remotePort) Then Return Null
'		Local stream:TStream = CreateSocketStream(socket)
'		WriteLine(stream, "GET /"+File+" HTTP/1.0")
'		WriteLine(stream, "Host: "+Host)
'		WriteLine(stream, "")
'		Local res$="x"
'		While res<>""
'			res=ReadLine(stream)
'			If Instr(res,"ice-audio-info")
'				Local pos:Int,w$
'				pos = Instr(res,"samplerate=")
'				If pos Then samplerate = Int(Mid$(res,pos+11,5))
'				pos = Instr(res,"channels=")
'				If pos Then channels = Int(Mid$(res,pos+9,1))
'			EndIf
'		Wend
'
'		If SampleRate=0 Or channels=0 Then Return Null
'		
'		Local This:MaxMod_OggStream = New MaxMod_OggStream
'		This.Socket = Socket
'		This.Stream 		= Stream
'		This.Sample_Rate 	= SampleRate 
''		If channels=1 This.STREAM_FORMAT=AL_FORMAT_MONO16 Else This.STREAM_FORMAT=AL_FORMAT_STEREO16
'
'		If Not Stream Return Null
'		This.ogg = Decode_Ogg(Stream,readfunc,seekfunc,closefunc,tellfunc,samples,channels,freq)
'		If Not This.ogg Return Null
'
'		Return This
'	EndFunction
 
	Method Stop()
'		Super.Stop
'		If Not Socket
			Read_Ogg( ogg,Null,0 )
			Stream.Seek(0); Stream_Pos=0
			Local channels:Int
			ogg = Decode_Ogg(Stream,readfunc,seekfunc,closefunc,tellfunc,Stream_Size,channels,SAMPLE_RATE)
'		EndIf
	EndMethod

	Method FillBuffer(SoundData:Int,Length:Int)
	
		If Not Length Return
	
		If STREAM_SIZE=0 Or (Stream_Pos+(Length/4))<Stream_Size
			Read_Ogg( ogg,Short Ptr(SoundData),Length )
			Stream_Pos:+(Length/4)
		Else
			Local n:Int,remainder:Int = (Stream_Size-(Stream_Pos))*4
			MemClear(Byte Ptr(SoundData),length)
			If remainder
				Read_Ogg( ogg,Byte Ptr(SoundData),remainder )
				Read_Ogg( ogg,Null,0 )
			EndIf
			Stream_Pos:+(remainder/4)
			If Stream_Loop = True
				Local channels:Int
				Stream.Seek(0); Stream_Pos=0
				ogg = Decode_Ogg(Stream,readfunc,seekfunc,closefunc,tellfunc,Stream_Size,channels,SAMPLE_RATE)
				FillBuffer(SoundData+remainder,Length-remainder)
			Else
				PlayStatus = False
				Stop
			EndIf
		EndIf

	EndMethod
	
	Method Free()
		Super.Free()
		Read_Ogg(ogg,Null,0)
		CloseStream(Stream)
'		If Socket CloseSocket(Socket)
	EndMethod

EndType
